package pc

import (
	"chess_platform/controllers"
	. "chess_platform/internal/common"
	"chess_platform/internal/token"
	"chess_platform/models/pc"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/astaxie/beego/context"
	"strconv"
	"strings"
)

type BaseUserInfo struct {
	Uid   int64    `json:"uid"`
	Name  string   `json:"name"`
	Ui    UserInfo `json:"ui"`
	Level int64    `json:"is_admin"` //账号等级管理员,1-超级管理员,2-公司管理员,3-区域管理员,4-普通账户
}

type BaseController struct {
	controllers.BaseController
	BaseUserInfo
}

type GrantController struct {
	BaseController
}

func (b *BaseController) Prepare() {

	b.Res = new(controllers.Response)
	LogPc.Debug("用户输入:" + string(b.Ctx.Input.RequestBody))
	LogPc.Debug(fmt.Sprintf("用户访问(ID:%v)url:%v", b.Uid, b.Ctx.Input.URL()))
}

func (b *BaseController) Finish() {
	data, _ := json.Marshal(b.Data["json"])
	LogPc.Debug(fmt.Sprintf("用户(ID:%v)访问url:%v返回值:%v", b.Uid, b.Ctx.Input.URL(), string(data)))
}

func (b *GrantController) Prepare() {
	LogPc.Debug("用户输入:" + string(b.Ctx.Input.RequestBody))
	LogPc.Debug("用户访问url:" + b.Ctx.Input.URL())
	b.Res = new(controllers.Response)
	var (
		t        controllers.Token
		tokenStr string
		ex       *token.Export
	)

	err := b.Unmarshal(&t)
	if err != nil || t.Token == "" {
		tokenStr = b.Ctx.Input.Header("token")
		if tokenStr == "" {
			if tokenStr == "" {
				tokenStr = b.Ctx.Request.PostFormValue("token")
				if tokenStr == "" {
					b.ResponseFail("未带token访问")
					return
				}
			}
		}
	}
	if tokenStr != "" {
		ex, err = token.Parse(tokenStr)
	} else {
		tokenStr = t.Token
		ex, err = token.Parse(tokenStr)
	}

	if err != nil || ex.GetTokenType() != TokenPc {
		LogPc.Error(fmt.Sprintf("token解析错误:%v,或不是此Pc类型的token", err))
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserUnauthorized
		b.Response()
		return
	}

	b.Uid = ex.GetId()
	b.Level = ex.GetLevel()

	//cache里不存在说明token已经过期了
	key := fmt.Sprintf("%v%v", KeyPcTokenCache, b.Uid)
	if ex.IsExpire() || !RedisCache.IsExist(key) {
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserExpire
		b.Response()
		return
	}

	//cache里的token与传进来的不一样的话表示此帐号在其它地方登录了
	tokenCache := RedisCache.GetString(key)
	if tokenCache != "" { // token存在缓存里
		if string(tokenCache) != tokenStr {
			b.Res.Code = ErrAlreadyLogin
			b.Res.Msg = MsgErrAlreadyLogin
			b.Response()
			return
		}
	} else { //token不存在缓存里
		b.Res.Code = ErrUserUnauthorized
		b.Res.Msg = MsgErrUserUnauthorized
		b.Response()
		return
	}

	keyAccessLimit := fmt.Sprintf("PcUserLimit-%v", b.Uid)
	if !AccessLimit(keyAccessLimit, Al.Frequency, Al.ExpireTime) {
		b.ResponseFail("操作过于频繁，请稍候再操作")
		return
	}

	v, ok := ex.GetInfo().(map[string]interface{})
	if ok {
		roleId := fmt.Sprintf("%v", v["role_id"])
		groupId := fmt.Sprintf("%v", v["group_id"])
		b.Ui.RoleId, _ = strconv.ParseInt(roleId, 10, 64)
		b.Ui.GroupId, _ = strconv.ParseInt(groupId, 10, 64)
	} else {
		b.ResponseFail("系统异常")
		return
	}

	LogPc.Debug(fmt.Sprintf("用户访问(ID:%v,Level:%v,RoleID:%v,GroupID:%v)url:%v", b.Uid, b.Level, b.Ui.RoleId, b.Ui.GroupId, b.Ctx.Input.URL()))
	/*-----------------------校验访问权限---------------------------*/
	if !b.IsSystemAdmin() { //如果不超级管理员,需要校验它的访问权限
		if !CheckPermission(b.Ctx, b.Ui.RoleId) {
			b.Res.Code = ErrUserForbidden
			b.Res.Msg = MsgErrUserForbidden
			b.Response()
			return
		}
	}
}

func CheckPermission(ctx *context.Context, roleId int64) bool {
	completeUri := strings.ToLower(strings.Split(ctx.Request.RequestURI, "?")[0])
	params := strings.Split(completeUri, "/")
	if len(params) < 4 {
		return false
	}
	parentModule := params[3]
	childModule := params[4]
	uri := strings.Join(params[2:], "/") //去掉前面的一版本字段(/v1)
	LogPc.Debug("访问的URI:" + "/" + uri)
	LogPc.Debug("parentModule:" + parentModule)
	LogPc.Debug("childModule:" + childModule)
	return pc.CheckAccess(parentModule, childModule, roleId)
}

//
func UserLevel(uid int64) int64 {
	o := NewDBOrm(DBChessCenter)
	user, err := pc.UserInfoById(uid, o)
	if err != nil {
		LogPc.Error(err.Error())
		return 0
	}
	if user == nil {
		err = errors.New(fmt.Sprintf("系统异常,用户(ID:%v)不存在", uid))
		LogPc.Error(err.Error())
		return 0
	}
	role, err := pc.RoleInfoById(user.RoleId, o)
	if err != nil {
		LogPc.Error(err.Error())
		return 0
	}
	if role == nil {
		err = errors.New(fmt.Sprintf("系统异常,用户(ID:%v)关联的角色(ID:%v)在数据库里不存在", uid, user.RoleId))
		LogPc.Error(err.Error())
		return 0
	}

	group, err := pc.GroupInfoById(user.GroupId, o)
	if err != nil {
		LogPc.Error(err.Error())
		return 0
	}
	if group == nil {
		err = errors.New(fmt.Sprintf("系统异常,用户(ID:%v)关联的大区(ID:%v)在数据库里不存在", uid, user.GroupId))
		LogPc.Error(err.Error())
		return 0
	}
	/*
		SystemAdmin  = 1 //系统内置的管理
		SpecialAdmin = 2 //系统内置角色的帐号
		OrdinaryUser = 3 //普通帐号
	*/
	if user.Mutable == 0 {
		return SystemAdmin
	} else if user.Mutable != 0 && role.Mutable == 0 {
		return SpecialAdmin
	} else if role.Mutable != 0 {
		return OrdinaryUser
	}
	return OrdinaryUser
}

func (b *GrantController) IsAdmin(uid ...int64) bool {
	var level int64
	if len(uid) == 1 {
		level = UserLevel(uid[0])
	} else {
		level = b.Level
	}
	if level != SystemAdmin && level != SpecialAdmin {
		return false
	}
	return true
}

func (b *GrantController) IsSystemAdmin(uid ...int64) bool {
	var level int64
	if len(uid) == 1 {
		level = UserLevel(uid[0])
	} else {
		level = b.Level
	}
	if level != SystemAdmin {
		return false
	}
	return true
}

func (b *GrantController) IsSpecialAdmin(uid ...int64) bool {
	var level int64
	if len(uid) == 1 {
		level = UserLevel(uid[0])
	} else {
		level = b.Level
	}
	if level != SpecialAdmin {
		return false
	}
	return true
}

func (b *GrantController) IsOrdinaryUser(uid ...int64) bool {
	var level int64
	if len(uid) == 1 {
		level = UserLevel(uid[0])
	} else {
		level = b.Level
	}
	if level != OrdinaryUser {
		return false
	}
	return true
}

//所属的大区是属于公司?, true-是,false-否
func (b *GrantController) IsCompany() bool {
	if b.Ui.GroupId == 0 {
		return true
	}
	return false
}

func (b *GrantController) NewLog(module, typ int64, msg string, detail map[string]interface{}) {
	go pc.NewOperationLog(b.Uid, module, typ, b.Ctx.Input.IP(), msg, detail)
}
